<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="ekbrs" id="ekbrs"><span data-lake-id="u7fac32bc" id="u7fac32bc">典型回答</span></h1>
  <p data-lake-id="u966b901a" id="u966b901a"><br></p>
  <p data-lake-id="uf56004d4" id="uf56004d4"><span data-lake-id="u51b3f7af" id="u51b3f7af">当不让使用redis分布式锁，或者集群不可用的时候，如何做到防止用户重复点击的功能呢？</span></p>
  <p data-lake-id="u0b5644f3" id="u0b5644f3"><span data-lake-id="u522255b5" id="u522255b5">​</span><br></p>
  <p data-lake-id="ud16f49ef" id="ud16f49ef"><span data-lake-id="ub2301da3" id="ub2301da3">有以下几个思路可以供大家参考：</span></p>
  <p data-lake-id="ue3606942" id="ue3606942"><span data-lake-id="u2d239881" id="u2d239881">​</span><br></p>
  <p data-lake-id="u037849d2" id="u037849d2"><span data-lake-id="u5c5e23f8" id="u5c5e23f8">1、首先就是前端需要做一些按钮置灰的动作，让用户点击一次之后，按钮就直接禁用调，让用户无法重复点击。但是有些情况可能没来得及置灰就重复点击了，或者有些用户自己绕过了置灰也可以点击。</span></p>
  <p data-lake-id="u1ec51a73" id="u1ec51a73"><span data-lake-id="ua0b38e97" id="ua0b38e97">​</span><br></p>
  <p data-lake-id="u84147422" id="u84147422"><span data-lake-id="u2578dfea" id="u2578dfea">2、可以通过token的机制避免重复提交，当用户访问页面的时候，请求后端服务拿到一个token，然后下一次接口点击的时候把token带过来，服务端对token进行验证，验证该token是否被使用过，如果没有被使用过才可以进行点击。验证的逻辑可以放在数据库中，通过数据库的悲观锁或者乐观锁都可以实现。</span></p>
  <p data-lake-id="u837e507b" id="u837e507b"><span data-lake-id="ube4d2ca6" id="ube4d2ca6">​</span><br></p>
  <p data-lake-id="u7bd09f4e" id="u7bd09f4e"><br></p>
  <p data-lake-id="ua28e9f45" id="ua28e9f45"><span data-lake-id="u9aacde2c" id="u9aacde2c">3、滑动窗口限流，滑动窗口限流是一种流量控制策略，用于控制在一定时间内允许执行的操作数量或请求频率。我们可以限制一分钟或者一秒钟内用户只能发起一次请求来防止重复点击。</span></p>
  <p data-lake-id="u39a38415" id="u39a38415"><span data-lake-id="u456af412" id="u456af412">​</span><br></p>
  <p data-lake-id="ue1a3518f" id="ue1a3518f"><span data-lake-id="ud02750fa" id="ud02750fa">​</span><br></p>
  <p data-lake-id="u6234c05f" id="u6234c05f"><span data-lake-id="u5ee82f67" id="u5ee82f67">4、可以使用布隆过滤器，他可以快速判断某个元素是否存在于集合中。可以在服务器端使用布隆过滤器记录某个操作是否已经被执行过，从而防止重复执行。</span></p>
  <p data-lake-id="ubf041f5e" id="ubf041f5e"><span data-lake-id="u1d42f98c" id="u1d42f98c">​</span><br></p>
  <blockquote data-lake-id="u556bc726" id="u556bc726">
   <p data-lake-id="u91bcdd63" id="u91bcdd63"><span data-lake-id="u0098339e" id="u0098339e">如果布隆过滤器不存在，则一定不存在，所以，如果没查到，说明一定没有幂等操作，直接执行就行了。</span></p>
   <p data-lake-id="u27661529" id="u27661529"><span data-lake-id="u0ef7306b" id="u0ef7306b">如果查询布隆过滤器发现有命中，则需要再服务数据库做一次幂等判断。</span></p>
   <p data-lake-id="u997af892" id="u997af892"><span data-lake-id="uc48e8b9d" id="uc48e8b9d">大多数情况下，需要幂等的情况占比小，所以可以用布隆过滤器做一次fail-fast的快速校验。</span></p>
  </blockquote>
  <p data-lake-id="u77241ea2" id="u77241ea2"><br></p>
  <p data-lake-id="u438c2791" id="u438c2791"><br></p>
  <p data-lake-id="u68125467" id="u68125467"><strong><span data-lake-id="ubcedb230" id="ubcedb230">Redis其实也是一个集中式的存储服务，在特殊情况下，如果无法使用，一般的做法都是降级成直接使用数据库。</span></strong></p>
 </body>
</html>